﻿/**
 * @file main.c
 * @brief 学生成绩管理系统
 */
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct student {
    char name[20]; // 学生姓名
    float* scores; // 存储所有课程成绩的数组
    struct student* next; // 下一个学生节点指针
} Student;

typedef struct course {
    char name[20]; // 课程名称
    struct course* next; // 下一个课程节点指针
} Course;

// 全局变量
Course* courseHead = NULL; // 课程头指针
Student* studentHead = NULL; // 学生头指针
int numCourses = 0; // 课程数量

// 函数声明
void clearScreen();
void printMenu();
void printCourseMenu();
void printStudentMenu();
void printScoreMenu();
void addCourse();
void modifyCourse();
void viewCourse();
void deleteCourse();
void addStudent();
void modifyStudent();
void viewStudent();
void addScore();
void viewAllScores();
void saveScore();
void sortScore();
void deleteStudent();
void modifyScore();

int main() {
    int choice;
    while (1) {
        clearScreen();
        printMenu();
        scanf("%d", &choice);
        switch (choice) {
        case 1:
            clearScreen();
            printCourseMenu();
            break;
        case 2:
            clearScreen();
            printStudentMenu();
            break;
        case 3:
            clearScreen();
            printScoreMenu();
            break;
        case 4:
            // 退出
            exit(0);
            break;
        default:
            printf("选择错误，请重新输入！\n");
            break;
        }
    }
    return 0;
}

/**
 * @brief 清屏函数
 */
void clearScreen() {
#ifdef _WIN32
    system("cls");
#else
    system("clear");
#endif // _WIN32
}

/**
 * @brief 打印主菜单
 */
void printMenu() {
    printf("学生成绩管理系统\n");
    printf("1.课程管理\n");
    printf("2.学生管理\n");
    printf("3.成绩管理\n");
    printf("4.退出\n");
}

/**
 * @brief 打印课程管理菜单
 */
void printCourseMenu() {
    int choice;
    while (1) {
        printf("课程管理\n");
        printf("1.录入课程\n");
        printf("2.修改课程\n");
        printf("3.查看课程\n");
        printf("4.删除课程\n");
        printf("5.返回\n");
        scanf("%d", &choice);
        switch (choice) {
        case 1:
            clearScreen();
            addCourse();
            break;
        case 2:
            clearScreen();
            modifyCourse();
            break;
        case 3:
            clearScreen();
            viewCourse();
            break;
        case 4:
            clearScreen();
            deleteCourse();
            break;
        case 5:
            return;
        default:
            printf("选择错误，请重新输入！\n");
            break;
        }
    }
}

/**
 * @brief 打印学生管理菜单
 */
void printStudentMenu() {
    int choice;
    while (1) {
        printf("学生管理\n");
        printf("1.录入学生\n");
        printf("2.修改学生\n");
        printf("3.查看学生\n");
        printf("4.给学生录入成绩\n");
        printf("5.查询指定学生成绩\n");
        printf("6.删除学生\n");
        printf("7.返回\n");
        scanf("%d", &choice);
        switch (choice) {
        case 1:
            clearScreen();
            addStudent();
            break;
        case 2:
            clearScreen();
            modifyStudent();
            break;
        case 3:
            clearScreen();
            viewStudent();
            break;
        case 4:
            clearScreen();
            addScore();
            break;
        case 5:
            clearScreen();
            viewAllScores();
            break;
        case 6:
            clearScreen();
            deleteStudent();
            break;
        case 7:
            return;
        default:
            printf("选择错误，请重新输入！\n");
            break;
        }
    }
}

/**
 * @brief 打印成绩管理菜单
 */
void printScoreMenu() {
    int choice;
    while (1) {
        printf("成绩管理\n");
        printf("1.保存成绩到本地\n");
        printf("2.全部成绩查看\n");
        printf("3.成绩修改\n");
        printf("4.返回\n");
        scanf("%d", &choice);
        switch (choice) {
        case 1:
            clearScreen();
            saveScore();
            break;
        case 2:
            clearScreen();
            viewAllScores();
            break;
        case 3:
            clearScreen();
            modifyScore();
            break;
        case 4:
            return;
        default:
            printf("选择错误，请重新输入！\n");
            break;
        }
    }
}

/**
 * @brief 添加课程
 */
void addCourse() {
    Course* newCourse = (Course*)malloc(sizeof(Course)); // 新建课程节点
    printf("请输入课程名称：");
    scanf("%s", newCourse->name); // 接收用户输入的课程名称
    newCourse->next = NULL; // 将下一个课程节点指针置为空

    if (courseHead == NULL) { // 如果课程头指针为空，即课程列表为空
        courseHead = newCourse; // 将新建的课程节点设为课程头指针
    }
    else {
        Course* temp = courseHead; // 临时指针指向课程头指针
        while (temp->next != NULL) { // 遍历课程列表，找到最后一个课程节点
            temp = temp->next;
        }
        temp->next = newCourse; // 将新建的课程节点接到最后一个课程节点的next
    }
    numCourses++; // 课程数量加1
    printf("课程添加成功！\n");
}

/**
 * @brief 修改课程
 */
void modifyCourse() {
    char name[20]; // 要修改的课程名称
    printf("请输入要修改的课程名称：");
    scanf("%s", name);
    Course* temp = courseHead;
    while (temp != NULL) {
        if (strcmp(temp->name, name) == 0) { // 找到要修改的课程
            printf("请输入新的课程名称：");
            scanf("%s", temp->name); // 修改课程名称
            printf("课程修改成功！\n");
            return;
        }
        temp = temp->next;
    }
    printf("未找到该课程！\n");
}

/**
 * @brief 查看课程
 */
void viewCourse() {
    Course* temp = courseHead;
    printf("课程列表：\n");
    while (temp != NULL) {
        printf("%s\n", temp->name); // 打印课程名称
        temp = temp->next;
    }
}

/**
 * @brief 删除课程
 */
void deleteCourse() {
    char name[20]; // 要删除的课程名称
    printf("请输入要删除的课程名称：");
    scanf("%s", name);
    Course* temp = courseHead;
    if (temp == NULL) { // 如果课程列表为空
        printf("课程列表为空！\n");
        return;
    }
    // 删除头节点
    if (strcmp(temp->name, name) == 0) { // 找到要删除的课程，即头节点为要删除的课程
        courseHead = courseHead->next; // 将头指针指向下一个节点
        free(temp); // 释放内存空间
        numCourses--; // 课程数量减1
        printf("课程删除成功！\n");
        return;
    }
    Course* pre = temp;
    temp = temp->next;
    while (temp != NULL) { // 遍历课程列表
        if (strcmp(temp->name, name) == 0) { // 找到要删除的课程
            pre->next = temp->next; // 将上一个节点的next指向下一个节点
            free(temp);
            numCourses--;
            printf("课程删除成功！\n");
            return;
        }
        pre = temp;
        temp = temp->next;
    }
    printf("未找到该课程！\n");
}

/**
 * @brief 添加学生
 */
void addStudent() {
    Student* newStudent = (Student*)malloc(sizeof(Student)); // 新建学生节点
    printf("请输入学生姓名：");
    scanf("%s", newStudent->name); // 接收用户输入的学生姓名
    newStudent->scores = (float*)malloc(numCourses * sizeof(float)); // 为课程成绩数组分配内存空间
    for (int i = 0; i < numCourses; i++) {
        newStudent->scores[i] = 0.0; // 初始化所有课程成绩为0
    }
    newStudent->next = NULL; // 将下一个学生节点指针置为空

    if (studentHead == NULL) { // 如果学生头指针为空，即学生列表为空
        studentHead = newStudent; // 将新建的学生节点设为学生头指针
    }
    else {
        Student* temp = studentHead; // 临时指针指向学生头指针
        while (temp->next != NULL) { // 遍历学生列表，找到最后一个学生节点
            temp = temp->next;
        }
        temp->next = newStudent; // 将新建的学生节点接到最后一个学生节点的next
    }
    printf("学生添加成功！\n");
}

/**
 * @brief 修改学生
 */
void modifyStudent() {
    char name[20]; // 要修改的学生姓名
    printf("请输入要修改的学生姓名：");
    scanf("%s", name);
    Student* temp = studentHead;
    while (temp != NULL) {
        if (strcmp(temp->name, name) == 0) { // 找到要修改的学生
            printf("请输入新的学生姓名：");
            scanf("%s", temp->name); // 修改学生姓名
            printf("学生修改成功！\n");
            return;
        }
        temp = temp->next;
    }
    printf("未找到该学生！\n");
}

/**
 * @brief 查看学生
 */
void viewStudent() {
    Student* temp = studentHead;
    printf("学生列表：\n");
    while (temp != NULL) {
        printf("%s\n", temp->name); // 打印学生姓名
        temp = temp->next;
    }
}

/**
 * @brief 给学生录入成绩
 */
void addScore() {
    char studentName[21]; // 学生姓名
    char courseName[21]; // 课程名称
    printf("请输入学生姓名：");
    scanf("%s", studentName);
    printf("请输入课程名称：");
    scanf("%s", courseName);
    float score; // 成绩
    printf("请输入成绩：");
    scanf("%f", &score);

    Student* studentTemp = studentHead;
    while (studentTemp != NULL) {
        if (strcmp(studentTemp->name, studentName) == 0) { // 找到要录入成绩的学生
            Course* courseTemp = courseHead;
            int index = 0; // 课程序号
            while (courseTemp != NULL) {
                if (strcmp(courseTemp->name, courseName) == 0) { // 找到要录入成绩的课程
                    studentTemp->scores[index] = score; // 将成绩录入学生的课程成绩数组中
                    printf("成绩录入成功！\n");
                    return;
                }
                courseTemp = courseTemp->next;
                index++;
            }
            printf("未找到该课程！\n");
            return;
        }
        studentTemp = studentTemp->next;
    }
    printf("未找到该学生！\n");
}

/**
 * @brief 查询所有学生成绩
 */
void viewAllScores() {
    printf("学生成绩表：\n");
    Student* studentTemp = studentHead;
    Course* courseTemp = courseHead;
    // 打印表头：课程名称
    printf("%-10s", "学生姓名");
    while (courseTemp != NULL) {
        printf("%-10s", courseTemp->name);
        courseTemp = courseTemp->next;
    }
    printf("\n");
    // 打印学生姓名和各课程成绩
    while (studentTemp != NULL) {
        printf("%-10s", studentTemp->name);
        int index = 0; // 课程序号
        while (index < numCourses) {
            printf("%-10.2f", studentTemp->scores[index]);
            index++;
        }
        printf("\n");
        studentTemp = studentTemp->next;
    }
}

/**
 * @brief 保存学生成绩到文件
 */
void saveScore() {
    FILE* file;
    file = fopen("score.txt", "w"); // 打开文件
    if (file == NULL) {
        printf("无法打开文件！\n");
        return;
    }

    Student* temp = studentHead;
    while (temp != NULL) {
        fprintf(file, "%s", temp->name); // 将学生姓名写入文件
        for (int i = 0; i < numCourses; i++) {
            fprintf(file, " %.2f", temp->scores[i]); // 将学生的各课程成绩写入文件
        }
        fprintf(file, "\n");
        temp = temp->next;
    }

    fclose(file); // 关闭文件
    printf("成绩保存成功！\n");
}

void sortScore() {
}

/**
 * @brief 删除学生
 */
void deleteStudent() {
    char name[20]; // 要删除的学生姓名
    printf("请输入要删除的学生姓名：");
    scanf("%s", name);
    Student* temp = studentHead;
    if (temp == NULL) { // 如果学生列表为空
        printf("学生列表为空！\n");
        return;
    }
    // 删除头节点
    if (strcmp(temp->name, name) == 0) { // 找到要删除的学生，即头节点为要删除的学生
        studentHead = studentHead->next; // 将头指针指向下一个节点
        free(temp->scores); // 释放成绩数组内存空间
        free(temp); // 释放学生节点内存空间
        printf("学生删除成功！\n");
        return;
    }
    Student* pre = temp;
    temp = temp->next;
    while (temp != NULL) { // 遍历学生列表
        if (strcmp(temp->name, name) == 0) { // 找到要删除的学生
            pre->next = temp->next; // 将上一个节点的next指向下一个节点
            free(temp->scores);
            free(temp);
            printf("学生删除成功！\n");
            return;
        }
        pre = temp;
        temp = temp->next;
    }
    printf("未找到该学生！\n");
}

/**
 * @brief 修改学生成绩
 */
void modifyScore() {
    char studentName[21]; // 学生姓名
    printf("请输入学生姓名：");
    scanf("%s", studentName);

    Student* temp = studentHead;
    while (temp != NULL) {
        if (strcmp(temp->name, studentName) == 0) { // 找到要修改成绩的学生
            printf("请输入课程名称：");
            char courseName[21];
            scanf("%s", courseName);
            int index = 0; // 课程序号
            Course* courseTemp = courseHead;
            while (courseTemp != NULL) {
                if (strcmp(courseTemp->name, courseName) == 0) { // 找到要修改成绩的课程
                    printf("请输入新的成绩：");
                    float newScore;
                    scanf("%f", &newScore);
                    temp->scores[index] = newScore; // 将新成绩赋值给学生的对应课程成绩
                    printf("成绩修改成功！\n");
                    return;
                }
                courseTemp = courseTemp->next;
                index++;
            }
            printf("未找到该课程！\n");
            return;
        }
        temp = temp->next;
    }
    printf("未找到该学生！\n");
}